import LOG4J from "@/common/utils/Log4j";
import { waiting, deepClone } from "@/js_sdk/utils/utils.js";

const log4j = LOG4J.getLogCat("BluetoothManagerStore");
log4j.log("这里是蓝牙vuex");

function ab2hex(buffer) {
	const hexArr = Array.prototype.map.call(new Uint8Array(buffer), function (bit) {
		return ("00" + bit.toString(16)).slice(-2);
	});
	return hexArr.join("");
}

function analysis(value) {
	return value;
}

function getAdvertisData(device) {
	const bytes = Array.prototype.map.call(new Uint8Array(device.advertisData), (bit) => ("00" + bit.toString(16)).slice(-2)).join(":");
	// console.log('bytes', bytes);

	const byteArr = bytes.split(":");

	if (byteArr.length < 6) {
		return "";
	} else if (byteArr.length === 6) {
		return byteArr.reverse().join(":").toUpperCase();
	} else if (byteArr.length === 8) {
		return byteArr.slice(-6).reverse().join(":").toUpperCase();
	}

	return byteArr
		.reverse()
		.slice(byteArr.length - 8, byteArr.length - 2)
		.join(":")
		.toUpperCase();
}

function checkDeviceWithKey(device, key) {
	const name = device.name || device.localName;
	if (!name) return false;
	if (name === key) return true;
	const deviceId = device.deviceId;
	if (deviceId === key) return true;
	const mac = getAdvertisData(device);
	if (mac === key) return true;
	return false;
}

/**
 * 「系统 位置信息」
 * 检查Android设备上的GPS状态
 * 此函数尝试通过Android的LocationManager服务来判断GPS是否已启用
 * 它主要用于在需要定位服务时，提前告知用户是否需要开启GPS
 */
function checkAndroidGPS() {
	try {
		// 导入Android上下文类，用于获取系统服务
		const context = plus.android.importClass("android.content.Context");
		// 导入LocationManager类，用于访问位置服务
		const locationManager = plus.android.importClass("android.location.LocationManager");
		// 获取当前活动的主实例
		const main = plus.android.runtimeMainActivity();
		// 从系统服务中获取位置服务实例
		const mainSvr = main.getSystemService(context.LOCATION_SERVICE);

		// 检查GPS提供者是否启用，即GPS是否打开
		const flag = mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER);
		// 记录GPS状态日志
		log4j.log("GPS", flag);

		return flag;
	} catch (error) {
		// 如果发生错误，记录错误日志
		log4j.error("GPS", error);
	}
}

/**
 * 「应用 位置信息」
 * 检查用户是否授权应用使用其位置信息
 *
 * 此函数通过调用uni.getAppAuthorizeSetting()方法获取当前应用的授权设置信息，
 * 并检查用户是否已经授权应用使用其位置信息
 *
 * @returns {boolean} 如果用户已授权应用使用位置信息，则返回true；否则返回false
 */
function checkAndroidAppUserLocation() {
	const result = uni.getAppAuthorizeSetting();
	const flag = result.locationAuthorized === "authorized";
	log4j.log("user location", flag);
	return flag;
}

/**
 * 「系统 蓝牙」
 * 检查Android设备的蓝牙设置
 *
 * 这个方法IOS和Android 是有差异的
 * IOS：系统蓝牙和APP蓝牙权限共享bluetoothEnabled状态 ，即 两个都打开则为true 否则为false
 * Android： 只针对系统蓝牙
 *
 * 此函数通过调用uni.getSystemSetting()方法获取系统设置信息，
 * 然后检查蓝牙是否已启用
 *
 * @returns {boolean} 蓝牙是否已启用
 */
function checkAndroidSetting() {
	// 获取系统设置信息
	const result = uni.getSystemSetting();
	// 打印检查结果以便调试
	console.log("checkAndroidSetting", result);
	// 返回蓝牙是否已启用的状态
	return result.bluetoothEnabled;
}

function checkAndroidBluetooth() {
	const permissions = [
		"android.permission.BLUETOOTH",
		"android.permission.BLUETOOTH_ADVERTISE",
		"android.permission.BLUETOOTH_SCAN",
		"android.permission.BLUETOOTH_ADMIN",
		"android.permission.BLUETOOTH_CONNECT",
		"android.permission.ACCESS_FINE_LOCATION",
	];

	return new Promise((resolve) => {
		plus.android.requestPermissions(permissions, resolve);
	});
}

/**
 * 「应用 IOS蓝牙授权」
 * 检查iOS设备的蓝牙权限
 *
 * 此函数通过导入iOS的CBManager类来检查应用是否具有使用蓝牙的权限
 * 它主要针对iOS 13及以上版本，因为蓝牙权限检查在iOS 13引入
 */
function checkIOSAppUserBluetooth() {
	// 导入iOS的CBManager类，用于蓝牙操作
	const CBManager = plus.ios.importClass("CBManager");
	// 检查应用对蓝牙的权限状态
	const authStatus = CBManager.authorization(); // iOS 13+
	// 输出蓝牙权限状态
	console.log("蓝牙的权限状态", authStatus);
	return authStatus === 3;
}

function checkIOSBluetooth() {
	const CBCentralManager = plus.ios.import("CBCentralManager");
	const cManager = new CBCentralManager().init();
	return cManager.state();
}

const CHECK_BLUETOOTH_AUTH_LOSS = {
	GPS: 0,
	BLUETOOTH: 1,
	USER_LOCATION: 2,
	USER_BLUETOOTH: 3,
	NEAR: 4,
};

/**
 * android的蓝牙权限判断集成
 */
async function checkAndroidBluetoothAuth(fn) {
	const lost = [];
	if (!checkAndroidGPS()) {
		// throw TypeError(CHECK_BLUETOOTH_AUTH_LOSS.GPS);
		lost.push({
			code: CHECK_BLUETOOTH_AUTH_LOSS.GPS,
			message: "未开启GPS",
		});
	}
	if (!checkAndroidAppUserLocation()) {
		// throw TypeError(CHECK_BLUETOOTH_AUTH_LOSS.USER_LOCATION);
		lost.push({
			code: CHECK_BLUETOOTH_AUTH_LOSS.USER_LOCATION,
			message: "APP未授权定位",
		});
	}
	if (!checkAndroidSetting()) {
		// throw TypeError(CHECK_BLUETOOTH_AUTH_LOSS.BLUETOOTH);
		lost.push({
			code: CHECK_BLUETOOTH_AUTH_LOSS.BLUETOOTH,
			message: "未开启蓝牙",
		});
	}

	if (lost.length === 0) {
		await checkAndroidBluetooth();
	}

	if (typeof fn === "function") {
		fn();
	}

	return lost;
}
async function checkIOSBluetoothAuth(fn) {
	if (typeof fn === "function") {
		fn();
	}
	checkIOSBluetooth();

	await new Promise((complete) => uni.openBluetoothAdapter({ complete }));
	await new Promise((complete) => uni.closeBluetoothAdapter({ complete }));
	// 系统蓝牙和app蓝牙共用
	const system_switch = checkAndroidSetting();
	// app蓝牙授权
	const user_switch = checkIOSAppUserBluetooth();

	console.log("system_switch", system_switch);
	console.log("user_switch", user_switch);

	const lost = [];

	if (!system_switch && !user_switch) {
		// 如果app权限没开 就先提示开app权限
		lost.push({
			code: CHECK_BLUETOOTH_AUTH_LOSS.USER_BLUETOOTH,
			message: "APP未授权蓝牙",
		});
	}
	if (!system_switch && user_switch) {
		// app权限开了 就代表系统蓝牙没开
		lost.push({
			code: CHECK_BLUETOOTH_AUTH_LOSS.BLUETOOTH,
			message: "系统未授权蓝牙",
		});
	}

	return lost;
}

/**
 * 蓝牙状态
 * @type {{UNINITIALIZED: number, INITIALIZED: number, INITFAILED: number, SEARCH: number, UNCONNECTED: number, CONNECTING: number, CONNECTED: number, NOTFOUND: number, TIMEOUT: number, DISCONNECTED: number}}
 * @readonly
 * @enum {number}
 *
 */
const BLUETOOTH_STATUS = Object.freeze({
	/** 未初始化 */
	UNINITIALIZED: 0,
	/** 初始化成功 */
	INITIALIZED: 1,
	/** 初始化失败 */
	INITFAILED: -1,

	/** 搜索 查询 searchType 和 searchStatus 2个字段 */
	SEARCH: 2,

	/** 未连接 */
	UNCONNECTED: 3,
	/** 连接中 */
	CONNECTING: 4,
	/** 已连接 */
	CONNECTED: 5,
	/** 连接超时 3次连接失败循环后提示：连接超时 */
	TIMEOUT: -4,
	/** 连接中断  连接成功后的断开提示：连接已断开 */
	DISCONNECTED: -5,
	/** 手动连接中断  连接成功后的断开提示：连接已断开 */
	MANUAL: -6,
});

const BLUETOOTH_STATUS_DESC = {
	0: "未初始化",
	1: "初始化完成",
	"-1": "初始化失败",
	2: "搜索",
	3: "未连接",
	4: "连接中",
	5: "已连接",
	"-4": "连接超时",
	"-5": "连接中断",
	"-6": "连接中断",
};

/**
 * 搜索类型
 * @type {{UNSEARCH: number, SEARCHING: number}}
 * @readonly
 * @enum {number}
 */
const SEARCH_TYPE = Object.freeze({
	/** 未搜索 */
	UNSEARCH: 0,
	/** 搜索中 */
	SEARCHING: 1,
});

const SEARCH_TYPE_DESC = {
	0: "未开启搜索",
	1: "搜索中",
};

/**
 * 搜索状态
 * @type {{UNSEARCH: number, SEARCHING: number, FOUND: number, NOTFOUND: number}}
 * @readonly
 * @enum {number}
 */
const SEARCH_STATUS = Object.freeze({
	/** 未搜索 */
	UNSEARCH: 0,
	/** 搜索中 */
	SEARCHING: 1,
	/** 搜索完成 */
	FOUND: 2,
	/** 搜索失败 */
	NOTFOUND: -2,
});

const SEARCH_STATUS_DESC = {
	0: "未搜索",
	1: "搜索中",
	2: "搜索完成",
	"-2": "搜索失败",
};

const BLUETOOTH_MTU_STATUS = Object.freeze({
	UNSET: 0, // 未设置
	SETTING: 1, // 设置中
	SET: 2, // 设置成功
	FAIL: -2, // 设置失败
});

const BLUETOOTH_MTU_STATUS_DESC = Object.freeze({
	0: "未设置",
	1: "设置中",
	2: "设置成功",
	"-2": "设置失败",
});

// 默认属性 冻结不可修改
const defaultState = Object.freeze({
	RETRY_LIMIT: 1,
	SERVICE_ID: "BAE80001-4F05-4503-8E65-3AF1F7329D1F",
	// OTA_SERVICE_ID: "583ff01-9B8B-5191-6142-22A4536EF123",
	SEARCH_DELAY: 6000,
});

const state = {
	authChecking: false,
	authMap: {
		gps: true,
		bluetooth: true,
		userLocation: true,
		userBluetooth: true,
	},
	authCheckInterrupt: false,

	autoLink: true, // 是否允许app自动使用缓存地址连接
	devices: [], // 发现的设备列表
	deviceMap: {}, // 发现的设备MAP
	connectedDevice: null, // 当前连接设备
	characteristics: {
		service: null,
		write: null, // 写入特征值
		notify: null, // 通知特征值
	},
	mtu: 512, // 最大传输单元
	listeners: new Map(), // 监听器集合
	isAndroid: uni.getSystemInfoSync().platform === "android",
	isIos: uni.getSystemInfoSync().platform === "ios",
	services: null,

	retryCount: 0,

	bluetoothStatus: BLUETOOTH_STATUS.UNINITIALIZED, // 蓝牙状态： 未初始化0；初始化完成1；搜索2；连接中3，连接失败4，连接成功5，连接断开6
	bluetoothMtuStatus: BLUETOOTH_MTU_STATUS.UNSET, // Mtu的设置状态
	// 搜索状态 分为几类：1、[搜索中， 不在搜索中]； 2、[未搜索， 搜索中， 搜索完成， 搜索失败]
	searchType: SEARCH_TYPE.UNSEARCH, // 不在搜索中:0; 搜索中:1
	searchStatus: SEARCH_STATUS.UNSEARCH, // 未搜索0； 搜索中1；搜索完成2；搜索失败3
	searchFilterFn: () => {},
	searchStopFn: () => {},
	searchKey: "",

	allConnectionComplete: false,

	available: [],

	page: "main", // 默认是main 搜索页是connect
};

const getters = {
	// 系统蓝牙开关
	needOpenBluetooth: (state) => state.authMap.bluetooth,
	// 搜索到的设备列表
	deviceList: (state) => state.devices,
	// 值
	bluetoothState: (state) => state.bluetoothStatus,
	searchType: (state) => state.searchType,
	searchStatus: (state) => state.searchStatus,
	// 描述
	bluetoothStateDesc: (state) => BLUETOOTH_STATUS_DESC[state.bluetoothStatus],
	searchStatusDesc: (state) => SEARCH_STATUS_DESC[state.searchStatus],
	searchTypeDesc: (state) => SEARCH_TYPE_DESC[state.searchType],

	linkComplete: (state) => state.allConnectionComplete,

	getAvailable: (state) => state.available,
	autoLink: (state) => state.autoLink,

	getPage: (state) => state.page,
};

const mutations = {
	CHANGE_CHECK_ING(state, checking) {
		state.authChecking = checking;
	},
	SET_AUTH_MAP(state, lostMap) {
		state.authMap = Object.assign(state.authMap, { ...lostMap });
	},
	CHANGE_AUTH_CHECK_INTERRUPT(state, interrupt) {
		state.authCheckInterrupt = interrupt;
	},
	CHANGE_AUTO_LINK(state, autoLink) {
		state.autoLink = autoLink;
	},
	UPDATE_DEVICES(state, device) {
		if (!device) return;
		const deviceId = device.deviceId;
		const macAddress = getAdvertisData(device);

		state.deviceMap[deviceId] = {
			...device,
			mac: macAddress,
		};

		log4j.log("设备列表", JSON.stringify(state.deviceMap[deviceId]));
		state.devices = Object.values(state.deviceMap);

		console.log("state.devices", state.devices);
	},
	CLEAR_DEVICES(state) {
		state.devices = [];
		state.deviceMap = {};
	},
	SET_CONNECTED_DEVICE(state, device) {
		state.connectedDevice = device;
		uni.setStorageSync("lastDevice", device ? device.deviceId : "");
	},
	UPDATE_SERVICES(state, services) {
		state.services = services;
	},
	UPDATE_CHARACTERISTICS(state, { write, notify, service }) {
		state.characteristics = { write, notify, service };
	},
	SET_MTU(state, mtu) {
		if (!state.isAndroid) return;
		state.mtu = Math.min(mtu, 512);
	},
	ADD_LISTENER(state, { event, callback }) {
		state.listeners.set(event, callback);
	},
	REMOVE_LISTENER(state, event) {
		state.listeners.delete(event);
	},

	UPDATE_RETRY_COUNT(state, count) {
		state.retryCount = count;
	},

	SET_SEARCH_FILTER(state, option = {}) {
		state.searchFilterFn = option.filter || (() => {});
		state.searchStopFn = option.stopNow || (() => {});
	},

	/**
	 * 变更蓝牙模块「整体」状态
	 */
	UPDATE_BLUETOOTH_STATUS(state, status) {
		state.bluetoothStatus = status;
	},

	/**
	 * 变更蓝牙mtu设置情况 如果是ios就不设置
	 * @param {*} state
	 * @param {*} status
	 */
	UPDATE_BLUETOOTH_MTU_STATUS(state, status) {
		state.bluetoothMtuStatus = status;
	},

	/**
	 * 变更蓝牙搜索状态「「类型」」
	 */
	UPDATE_SEARCH_TYPE(state, type) {
		state.searchType = type;
	},
	/**
	 * 变更蓝牙搜索「状态」
	 */
	UPDATE_SEARCH_STATUS(state, status) {
		state.searchStatus = status;
	},

	SET_SEARCH_KEY(state, key) {
		state.searchKey = key;
	},

	SET_ALL_COMPLETE(state, complete) {
		state.allConnectionComplete = complete;
	},

	SAVE_AVAILABLE(state, status) {
		state.available.push(status);
	},

	CHANGE_PAGE(state, page) {
		state.page = page;
	},

	RESET_STATE(st) {
		Object.assign(st, deepClone(state));
	},
};

const initAndSearchActions = {
	changePage({ commit }, page) {
		commit("CHANGE_PAGE", page);
	},

	async checkPermission({ commit, state }) {
		try {
			let lostResult = [];
			if (state.isIos) {
				lostResult = await checkIOSBluetoothAuth(() => {
					commit("CHANGE_CHECK_ING", true);
				});
			} else {
				lostResult = checkAndroidBluetoothAuth(() => {
					commit("CHANGE_CHECK_ING", true);
				});
			}

			const lostMap = {
				gps: true,
				bluetooth: true,
				userLocation: true,
				userBluetooth: true,
			};

			lostResult.forEach(({ code }) => {
				if (code === 0) {
					// 没开GPS
					lostMap.gps = false;
				}
				if (code === 1) {
					// 没开蓝牙
					lostMap.bluetooth = false;
				}
				if (code === 2) {
					// 没授权位置
					lostMap.userLocation = false;
				}
				if (code === 3) {
					// 没授权蓝牙
					lostMap.userBluetooth = false;
				}
			});
			commit("SET_AUTH_MAP", lostMap);
		} finally {
			commit("CHANGE_CHECK_ING", false);
		}

		console.log("state auth map", state.authMap);
		return state.authMap;
	},

	changeAuthCheckInterrupt({ commit }, Interrupt) {
		commit("CHANGE_AUTH_CHECK_INTERRUPT", Interrupt);
	},

	changeAutoLink({ commit }, autoLink) {
		commit("CHANGE_AUTO_LINK", autoLink);
	},
	// 初始化蓝牙模块
	async initBluetooth({ commit }) {
		try {
			const result = await new Promise((success, fail) => {
				uni.openBluetoothAdapter({ success, fail });
			});
			log4j.log("蓝牙初始化成功", JSON.stringify(result));
			commit("UPDATE_BLUETOOTH_STATUS", BLUETOOTH_STATUS.INITIALIZED);

			return result;
		} catch (err) {
			log4j.error("蓝牙初始化失败", JSON.stringify(err));
			commit("UPDATE_BLUETOOTH_STATUS", BLUETOOTH_STATUS.INITFAILED);
			return null;
		}
	},

	async getBluetoothAdapterState() {
		try {
			const result = await new Promise((success, fail) => {
				uni.getBluetoothAdapterState({ success, fail });
			});
			log4j.log("蓝牙模块状态", JSON.stringify(result));
			return result;
		} catch (err) {
			log4j.error("蓝牙模块状态获取失败", JSON.stringify(err));
			return null;
		}
	},

	// 关闭蓝牙模块
	async closeBluetooth({ commit }) {
		try {
			const result = await new Promise((success, fail) => {
				uni.closeBluetoothAdapter({ success, fail });
			});
			log4j.log("蓝牙关闭成功", JSON.stringify(result));
			return result;
		} catch (error) {
			log4j.error("蓝牙关闭失败", JSON.stringify(error));
			return null;
		} finally {
			commit("UPDATE_BLUETOOTH_STATUS", BLUETOOTH_STATUS.UNINITIALIZED);
		}
	},

	// 通用设备搜索逻辑
	async _scanDevices({ state, commit }, fnOptions) {
		if ([BLUETOOTH_STATUS.UNINITIALIZED, BLUETOOTH_STATUS.INITFAILED].includes(state.bluetoothStatus)) return;

		commit("CLEAR_DEVICES");
		commit("SET_SEARCH_FILTER", fnOptions);

		try {
			log4j.log("蓝牙开启搜索");
			const result = await new Promise((success, fail) => {
				uni.startBluetoothDevicesDiscovery({
					allowDuplicatesKey: false,
					powerLevel: "high",
					interval: fnOptions.type === "all" ? 1000 : 20, // 1000 20
					success,
					fail,
				});
			});
			log4j.log("蓝牙开启搜索成功", JSON.stringify(result));
			commit("UPDATE_BLUETOOTH_STATUS", BLUETOOTH_STATUS.SEARCH);
			commit("UPDATE_SEARCH_TYPE", SEARCH_TYPE.SEARCHING);
			fnOptions.timeout();
		} catch (error) {
			log4j.error("蓝牙开启搜索失败", JSON.stringify(error));
			commit("UPDATE_SEARCH_TYPE", SEARCH_TYPE.UNSEARCH);
		}
	},

	/**
	 * 连接搜索 搜索所有breo设备
	 */
	async searchAllRingDevices({ dispatch, commit }) {
		// || (device.name || device.localName).includes("DeRing")
		// (device.name || device.localName).includes("uAita") ||
		//  || (device.name || device.localName).includes("R0 ")
		commit("SET_SEARCH_KEY", "");
		dispatch("_scanDevices", {
			filter: (device) => (device.name || device.localName).includes("BCL") || (device.name || device.localName).includes("R0 "),
			timeout: async () => {
				await waiting(defaultState.SEARCH_DELAY);
				await dispatch("_stopScanDevices", "all");
			},
			async stopNow() {
				await dispatch("_stopScanDevices", "specify");
			},
			type: "all",
		});
	},

	/**
	 * 指定名称的breo设备搜索
	 *
	 * @param {String} searchKey  设备name或者localName 或者设备deviceId 或者设备mac地址
	 */
	async searchSpecifyRingDevice({ dispatch, commit, state }, searchKey) {
		searchKey = searchKey || state.searchKey;
		console.log('💍🐎 ===> ', searchKey);
		
		if (!searchKey && !state.searchKey) return Promise.reject(new Error("name is required"));
		commit("SET_SEARCH_KEY", searchKey);
		dispatch("_scanDevices", {
			filter: (device) => checkDeviceWithKey(device, searchKey),
			timeout: async () => {
				await waiting(defaultState.SEARCH_DELAY * 2);
				await dispatch("_stopScanDevices", "specify");
				return true;
			},
			async stopNow() {
				await dispatch("_stopScanDevices", "specify");
				if (!state.autoLink && state.deviceList.length === 1) {
					dispatch("connectDevice", state.deviceList[0]);
				}
				return true;
			},
			type: "specify",
		});
	},

	async resetSearchState({ commit }) {
		commit("SET_SEARCH_KEY", "");
		commit("UPDATE_SEARCH_STATUS", SEARCH_STATUS.UNSEARCH);
		commit("CLEAR_DEVICES");
	},

	/**
	 * 停止搜索
	 */
	async _stopScanDevices({ commit, state }) {
		try {
			const result = await new Promise((success, fail) => {
				uni.stopBluetoothDevicesDiscovery({
					success,
					fail,
				});
			});
			log4j.log("停止搜索成功", JSON.stringify(result));
			if (![BLUETOOTH_STATUS.CONNECTED, BLUETOOTH_STATUS.CONNECTING].includes(state.bluetoothStatus)) {
				// 将蓝牙状态改为『搜索』状态
				commit("UPDATE_BLUETOOTH_STATUS", BLUETOOTH_STATUS.SEARCH);
				// 将搜索类型改为『不在搜索』
				commit("UPDATE_SEARCH_TYPE", SEARCH_TYPE.UNSEARCH);

				// 如果搜索到设备，则将搜索状态改为『搜索到』，否则改为『未搜索到』
				if (state.devices.length > 0) {
					commit("UPDATE_SEARCH_STATUS", SEARCH_STATUS.FOUND);
				} else {
					commit("UPDATE_SEARCH_STATUS", SEARCH_STATUS.NOTFOUND);
				}
			}
		} catch (error) {
			log4j.log("停止搜索失败", JSON.stringify(error));
		}
	},
};

// 续接store中的actions
const connectAndCharacteristicActions = {
	// 设备连接
	async connectDevice({ state, commit, dispatch }, device) {
		if ([BLUETOOTH_STATUS.UNINITIALIZED, BLUETOOTH_STATUS.INITFAILED].includes(state.bluetoothStatus)) return;
		log4j.log("要连接的设备:", JSON.stringify(device));

		try {
			commit("UPDATE_BLUETOOTH_STATUS", BLUETOOTH_STATUS.CONNECTING);
			console.log("要🔗的🆔", device.deviceId);

			const result = await new Promise((success, fail) => {
				uni.createBLEConnection({
					deviceId: device.deviceId,
					timeout: 20000,
					success,
					fail,
				});
			});

			log4j.log("连接成功:", result);
			await waiting(2000);
			await dispatch("getServices", device);
			commit("SET_CONNECTED_DEVICE", device);
		} catch (error) {
			log4j.error("连接失败:", JSON.stringify(error));
			await dispatch("handleConnectFailure", {
				device,
				error,
			});
		}
	},

	async getServices({ commit, dispatch, state }, device) {
		try {
			// 获取服务与特征值
			const { services } = await new Promise((success, fail) => {
				uni.getBLEDeviceServices({ deviceId: device.deviceId, success, fail });
			});
			console.log("获取服务与特征值 1 ", services);

			if (!services.length) {
				dispatch("getServices", device);
				return;
			}

			commit("UPDATE_SERVICES", services);

			const { characteristics } = await new Promise((success, fail) => {
				uni.getBLEDeviceCharacteristics({
					deviceId: device.deviceId,
					serviceId: defaultState.SERVICE_ID,
					success,
					fail,
				});
			});

			console.log("获取服务与特征值 2 ", characteristics);

			// 保存特征值
			const writeChar = characteristics.find((c) => c.properties.write);
			const notifyChar = characteristics.find((c) => c.properties.notify);
			commit("UPDATE_CHARACTERISTICS", {
				service: defaultState.SERVICE_ID,
				write: writeChar.uuid,
				notify: notifyChar.uuid,
			});

			commit("UPDATE_RETRY_COUNT", 0);

			const notify = await dispatch("notify", device);

			console.log("启动通知", notify);

			if (state.isAndroid) {
				commit("UPDATE_BLUETOOTH_MTU_STATUS", BLUETOOTH_MTU_STATUS.SETTING);
				await waiting(1000);
				const result1 = await dispatch("setMtu", device);
				console.log("result1", result1);
				// await waiting(1000);
				// const result2 = await dispatch("setMtu", device);
				// console.log("result2", result2);
				await waiting(1000);
			} else {
				commit("UPDATE_BLUETOOTH_MTU_STATUS", BLUETOOTH_MTU_STATUS.SET);
			}

			commit("SET_ALL_COMPLETE", true);
		} catch (error) {
			console.log("获取服务与特征值失败", error);
			if (
				[BLUETOOTH_STATUS.UNINITIALIZED, BLUETOOTH_STATUS.INITFAILED].includes(state.bluetoothStatus) ||
				state.bluetoothStatus !== BLUETOOTH_STATUS.CONNECTED
			) {
				return;
			}
			dispatch("getServices", device);
			commit("SET_ALL_COMPLETE", false);
		}
	},

	async setMtu(_, device) {
		// 设置MTU（iOS除外）
		return await new Promise((success, fail) => {
			console.log("设置mtu");
			uni.setBLEMTU({
				deviceId: device.deviceId,
				mtu: 512,
				success,
				fail,
			});
		});
	},

	async notify({ state }, device) {
		// 开启通知监听
		return await new Promise((success, fail) => {
			uni.notifyBLECharacteristicValueChange({
				deviceId: device.deviceId,
				serviceId: defaultState.SERVICE_ID,
				characteristicId: state.characteristics.notify,
				state: true,
				success,
				fail,
			});
		});
	},

	// 连接失败处理
	async handleConnectFailure({ state, dispatch, commit }, { device, error }) {
		const code = error.errCode || error.code;
		if (code === 10010 || code === -1) {
			// 已连接
			commit("UPDATE_BLUETOOTH_STATUS", BLUETOOTH_STATUS.CONNECTED);
			return;
		}
		// -1 是意外断开重连
		const needSearchErrorCodes = [10012, 10013, 10002, 10003];
		if (needSearchErrorCodes.includes(code)) {
			try {
				console.log("先中断蓝牙连接");
				await dispatch("disConnectDevice");
			} finally {
				log4j.log("连接超时 或者 deviceId为空", JSON.stringify(error));
				if (state.retryCount >= defaultState.RETRY_LIMIT) {
					log4j.log("重试次数已达上限，停止重试, 需用户手动点击重新搜索连接");
					commit("UPDATE_BLUETOOTH_STATUS", BLUETOOTH_STATUS.MANUAL);
					return;
				}
				await dispatch("closeBluetooth");
				await dispatch("initBluetooth");
				dispatch("searchSpecifyRingDevice", device.deviceId);
				commit("UPDATE_RETRY_COUNT", state.retryCount + 1);
				await dispatch("changeAutoLink", false);
			}
		}
	},

	async disConnectDevice({ state, commit }) {
		if (!state.connectedDevice) return;
		console.log("state.connectedDevice", state.connectedDevice);

		try {
			const result = new Promise((success, fail) => {
				uni.closeBLEConnection({
					deviceId: state.connectedDevice.deviceId,
					success,
					fail,
				});
			});
			commit("UPDATE_BLUETOOTH_STATUS", BLUETOOTH_STATUS.MANUAL);
			// commit("UPDATE_BLUETOOTH_STATUS", BLUETOOTH_STATUS.DISCONNECTED);
			log4j.log("断开链接成功", JSON.stringify(result));
			return result;
		} catch (error) {
			log4j.error("断开链接失败", JSON.stringify(error));
			return null;
		}
	},
};

const listenersActions = {
	addNotifyListener({ commit, dispatch }, { event, callback }) {
		if (!event) return;
		commit("ADD_LISTENER", { event, callback });
	},

	removeNotifyListener({ commit }, event) {
		commit("REMOVE_LISTENER", event);
	},
	/**
	 * 监听蓝牙适配器状态
	 */
	listenBluetoothAdapterStateChange({ state, commit }) {
		log4j.log("注册全局蓝牙状态监听事件");
		uni.onBluetoothAdapterStateChange((res) => {
			if (state.isIos && state.authChecking) return;
			log4j.log("adapterState changed, now is", JSON.stringify(res));
			console.log(state.available.length > 0 && state.available.slice(-1) === res.available);

			if (state.available.length > 0 && state.available.slice(-1)[0] === res.available) return;
			const status = state.bluetoothStatus;
			console.log("蓝牙状态", status, BLUETOOTH_STATUS_DESC[status]);
			if (status === BLUETOOTH_STATUS.CONNECTED && !res.available) {
				// 被强迫断开
				commit("UPDATE_BLUETOOTH_STATUS", BLUETOOTH_STATUS.DISCONNECTED);
			}

			if (!res.available) {
				commit("UPDATE_BLUETOOTH_STATUS", BLUETOOTH_STATUS.INITFAILED);
			}

			commit("SAVE_AVAILABLE", res.available);
		});
	},

	/**
	 * 监听蓝牙数据接收
	 */
	listenBluetoothCharacteristicValueChange({ state, rootState }) {
		log4j.log("注册全局蓝牙数据接收事件");
		console.log("token", uni.getStorageSync("userToken"));

		uni.onBLECharacteristicValueChange((res) => {
			if (!state.listeners || state.listeners.size < 0) return;
			const data = analysis(ab2hex(res.value));
			for (const [event, callback] of state.listeners) {
				if (rootState.modules.some((module) => event.indexOf(module) === 0)) {
					callback(data, { root: true });
				} else {
					callback(data);
				}
			}
		});
	},

	/**
	 * 监听蓝牙搜索设备返回
	 */
	listenBluetoothDeviceFoundChange({ commit, state }) {
		log4j.log("注册全局蓝牙搜索事件");

		uni.onBluetoothDeviceFound((res) => {
			commit("UPDATE_SEARCH_STATUS", SEARCH_STATUS.SEARCHING);
			if (!res.devices[0].name && !res.devices[0].localName) return;
			// console.log("res", res.devices[0].name, res.devices[0].localName);
			const device = res.devices.find(state.searchFilterFn);
			if (!device) return;
			console.log("device", state.searchKey);
			commit("UPDATE_DEVICES", device);
			if (state.searchKey && device) {
				state.searchStopFn();
			}
		});
	},

	/**
	 * 监听蓝牙连接变化
	 */
	listenBluetoothConnectionStateChange({ commit, dispatch, state }) {
		log4j.log("注册全局蓝牙连接事件");
		uni.onBLEConnectionStateChange((res) => {
			log4j.log("蓝牙连接状态变化", JSON.stringify(res));
			if (res.connected) {
				commit("UPDATE_BLUETOOTH_STATUS", BLUETOOTH_STATUS.CONNECTED);
			} else {
				// 如果没有记录已连接的设备则不向下处理
				if (!state.connectedDevice) return;
				if (state.connectedDevice) {
					commit("SET_CONNECTED_DEVICE", null);
				}

				console.log("state.connectedDevice", state.connectedDevice);
				console.log("当前状态", state.bluetoothStatus);

				// 先判断之前是否是连接成功的状态
				if (state.bluetoothStatus === BLUETOOTH_STATUS.DISCONNECTED) {
					// 如果是就要重连
					console.log("👌🏻 需要重连");
					dispatch("handleConnectFailure", {
						device: res,
						error: {
							errCode: -1,
						},
					});
				} else if (state.bluetoothStatus === BLUETOOTH_STATUS.MANUAL) {
					// 如果是手动的就不再重连
					console.log("🙅🏻‍♀️ 不需要重连");
				}

				// 只有在被动断开连接的情况 是disconnected ； 如果是app自动调用disconnect方法则状态是manual即自动断开
				if (state.bluetoothStatus !== BLUETOOTH_STATUS.MANUAL) {
					console.log("非手动关闭蓝牙 记录状态");
					commit("UPDATE_BLUETOOTH_STATUS", BLUETOOTH_STATUS.DISCONNECTED);
				}
				commit("SET_ALL_COMPLETE", false);
			}
		});
	},
};

const bluetoothAuthRelatedActions = {
	intoSystemBluetoothSetting({ state }) {
		log4j.log("进入系统蓝牙设置");
		if (state.isAndroid) {
			//进入Android系统蓝牙设置页面
			var Intent = plus.android.importClass("android.content.Intent");
			var Settings = plus.android.importClass("android.provider.Settings");
			var intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
			plus.android.runtimeMainActivity().startActivity(intent);
		} else if (state.isIos) {
			//进入IOS系统设置页面
			// plus.runtime.openURL("App-Prefs:root=Bluetooth");
			const UIApplication = plus.ios.importClass("UIApplication");
			const settingsURL = plus.ios.importClass("NSURL").URLWithString("App-Prefs:Bluetooth");
			UIApplication.sharedApplication().openURL(settingsURL);
		}
	},

	intoSystemLocationSetting({ state }) {
		if (state.isIos) return;
		log4j.log("进入系统定位设置");
		var Intent = plus.android.importClass("android.content.Intent");
		var Settings = plus.android.importClass("android.provider.Settings");
		var intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
		plus.android.runtimeMainActivity().startActivity(intent);
	},

	intoAppBluetoothSetting() {
		log4j.log("进入应用权限设置");
		uni.openAppAuthorizeSetting();
	},
};

export { BLUETOOTH_STATUS, SEARCH_STATUS, SEARCH_TYPE, SEARCH_STATUS_DESC, BLUETOOTH_STATUS_DESC, BLUETOOTH_MTU_STATUS, BLUETOOTH_MTU_STATUS_DESC };

export default {
	namespaced: true,
	state: deepClone(state),
	getters,
	mutations,
	actions: {
		...initAndSearchActions,
		...connectAndCharacteristicActions,
		...listenersActions,
		...bluetoothAuthRelatedActions,
	},
};
